﻿
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using RilattackLibrary;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace RilattackLibrary
{
    public class Map
    {
        public static Map _instance;
        public static Map Instance {
            get {
                if(_instance == null)
                {
                    _instance = new Map();
                }
                return _instance;
            }
        }

        private Rectangle getblocFromType(BlockType type)
        {
            int tileSize = 16;
            int tileSpacing = 2;
            switch (type)
            {
                case BlockType.borderTL1:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 21,
                        tileSpacing + (tileSpacing + tileSize) * 16, 16, 16);
                case BlockType.borderT1:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 22,
                        tileSpacing + (tileSpacing + tileSize) * 16, 16, 16);
                case BlockType.borderTR1:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 23,
                        tileSpacing + (tileSpacing + tileSize) * 16, 16, 16);
                case BlockType.borderL1:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 21,
                        tileSpacing + (tileSpacing + tileSize) * 17, 16, 16);
                case BlockType.borderR1:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 23,
                        tileSpacing + (tileSpacing + tileSize) * 17, 16, 16);
                case BlockType.borderBL1:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 21,
                        tileSpacing + (tileSpacing + tileSize) * 18, 16, 16);
                case BlockType.borderB1:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 22,
                        tileSpacing + (tileSpacing + tileSize) * 18, 16, 16);
                case BlockType.borderBR1:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 23,
                        tileSpacing + (tileSpacing + tileSize) * 18, 16, 16);
                case BlockType.softpenteR1:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 24,
                        tileSpacing + (tileSpacing + tileSize) * 16, 16, 16);
                case BlockType.softpenteR2:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 25,
                        tileSpacing + (tileSpacing + tileSize) * 16, 16, 16);
                case BlockType.softpenteIR1:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 24,
                        tileSpacing + (tileSpacing + tileSize) * 17, 16, 16);
                case BlockType.softpenteIR2:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 25,
                        tileSpacing + (tileSpacing + tileSize) * 17, 16, 16);
                case BlockType.softpenteL1:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 25,
                        tileSpacing + (tileSpacing + tileSize) * 20, 16, 16);
                case BlockType.softpenteL2:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 24,
                        tileSpacing + (tileSpacing + tileSize) * 20, 16, 16);
                case BlockType.softpenteIL1:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 25,
                        tileSpacing + (tileSpacing + tileSize) * 21, 16, 16);
                case BlockType.softpenteIL2:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 24,
                        tileSpacing + (tileSpacing + tileSize) * 21, 16, 16);
                case BlockType.penteR:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 24,
                        tileSpacing + (tileSpacing + tileSize) * 18, 16, 16);
                case BlockType.penteL:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 25,
                        tileSpacing + (tileSpacing + tileSize) * 18, 16, 16);
                case BlockType.penteIR:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 25,
                        tileSpacing + (tileSpacing + tileSize) * 19, 16, 16);
                case BlockType.penteIL:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 24,
                        tileSpacing + (tileSpacing + tileSize) * 19, 16, 16);
                case BlockType.emptyBloc:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 20,
                        tileSpacing + (tileSpacing + tileSize) * 23, 16, 16);
                case BlockType.plainBloc:
                default:
                    return new Rectangle(tileSpacing + (tileSpacing + tileSize) * 22,
                         tileSpacing + (tileSpacing + tileSize) * 17, 16, 16);
            }

        }

        public List<MapTile> CreateMapElements(Texture2D spriteMap, int blockWidth, int blockHeight, double destSizeFactor)
        {
            int[,] mapPrototype = new int[,] {
            { 1, 1, 1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,18, 1, 1, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,18, 1, 1, 1, 1, 1, 1, 1, 1 },
            { 1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 1, 1, 1, 1, 1, 1, 1 },
            { 1, 1, 6, 0,18, 3,19, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,18, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 3, 1, 1, 6, 0, 0, 0,21, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 1, 1, 1, 6, 0, 0, 0, 0, 5,19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,21, 8, 8, 8, 1, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 1, 1, 1, 7, 0, 0, 0, 0, 9, 1,19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 1, 1, 6, 0, 0, 0, 0, 0, 0, 9, 1, 3,19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 5, 1, 1, 3, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 1, 8, 1, 4, 0, 0, 0, 0, 0, 0, 5, 1, 1, 1, 1,20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,18, 3,19, 1, 1, 1, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 6, 0, 9, 7, 0, 0, 0, 0, 0, 0, 5, 1, 1, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,21, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,21, 8, 8, 1, 1, 1, 1 },
            { 1, 1, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,21, 7, 0, 0, 0, 0, 0, 0, 0, 0,10,14,10,14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 1, 1 },
            { 8, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 3, 1, 1, 1, 1, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 3, 3, 1, 1, 1, 1 },
            { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,21, 1, 1, 1, 1, 1, 1, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,11, 1, 1, 1, 1, 1, 1, 1, 1 },
            { 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 1, 1, 1, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,10, 1, 8, 1, 1, 1, 1, 1, 1, 1 },
            { 0, 0, 0, 0, 0, 2, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 1, 1, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,21,20, 0,21, 1, 1, 1, 1, 1, 1 },
            { 0, 0, 0, 2, 3, 1, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,21, 8, 1, 1, 1, 1 },
            { 0, 0, 2, 1, 1, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,21, 1, 1, 1 },
            { 0, 2, 1, 1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,21, 1, 1 },
            { 3, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,10,14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1 },
            { 1, 1, 1, 1, 1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0,18, 1, 1 },
            { 1, 1, 1, 1, 1, 1, 6, 0, 0, 0, 2,19, 0, 0, 0, 0, 0, 0, 0,18, 3, 3,19, 0, 0, 0, 0, 0, 0, 0, 0,18,19, 0, 2, 1, 1, 1,20, 0, 0, 0, 0, 0, 0, 0, 0,21, 1, 1 },
            { 1, 1, 1, 1, 1, 1, 7, 0, 0, 0, 9, 8,19, 0, 0, 0, 0, 0,18, 1, 1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 9, 1, 3, 1, 1, 8,20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1 },
            { 1, 1, 1, 1, 1, 7, 0, 0, 0, 0, 0, 0,21,19, 0,18, 3, 3, 1, 1, 1, 1, 1,19, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1 },
            { 1, 1, 1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0,21, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1,19, 0, 0, 0, 0, 0, 0, 0, 5, 1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 1, 1 },
            { 1, 1, 1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,19, 0, 0, 0, 0, 0, 2, 1, 1, 1, 6, 0,10,14, 0, 2, 4, 0,18,19, 0, 5, 1, 1, 1 },
            { 1, 1, 1, 1, 1, 4, 0, 2, 4, 0, 0, 0, 0, 0, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,19, 0, 0, 0, 0, 5, 1, 1, 1, 1, 3, 1, 1, 3, 1, 1, 3, 1, 1, 3, 1, 1, 1, 1 },
            { 1, 1, 1, 1, 1, 7, 0, 9, 1, 3,19,10,14,18, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,19, 0, 0, 0,21, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
            { 1, 1, 1, 1, 7, 0, 0, 0, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,19, 0, 0, 0, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
            { 1, 1, 1,20, 0, 0, 0, 0, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,19, 0,18, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
            };

            int mapYSize = mapPrototype.GetLength(1);
            int mapXSize = mapPrototype.GetLength(0);
            List<MapTile> mapElements = new List<MapTile>();

            int destBlockWidth = Convert.ToInt32(Convert.ToDouble(blockWidth) * destSizeFactor);
            int destBlockHeight = Convert.ToInt32(Convert.ToDouble(blockHeight) * destSizeFactor);

            for (int x = 0; x < mapXSize; x++)
            {
                for (int y = 0; y < mapYSize; y++)
                {
                    mapElements.Add(
                        new MapTile()
                        {
                            Source = getblocFromType((BlockType)mapPrototype[x, y]),
                            Dest = new Rectangle(y * destBlockWidth, x * destBlockHeight, destBlockWidth, destBlockHeight),
                            Image = spriteMap,
                            Type = (BlockType)mapPrototype[x, y]
                        });
                }
            }
            return mapElements;
        }

        public static List<MapTile> FindMapTilesByPosition(List<GraphicObject> graphicObjects, Rectangle rect)
        {
            return graphicObjects
                    .Where(actor => 
                        (actor.Dest.X >= rect.X && actor.Dest.X + actor.Dest.Width <= rect.X + rect.Width)
                        ||
                        (actor.Dest.X >= rect.X && actor.Dest.X <= rect.X + rect.Width)
                        ||
                        (actor.Dest.X + actor.Dest.Width >= rect.X && actor.Dest.X + actor.Dest.Width <= rect.X + rect.Width)

                    )
                    .Where(actor =>
                        (actor.Dest.Y >= rect.Y && actor.Dest.Y + actor.Dest.Height <= rect.Y + rect.Height)
                        ||
                        (actor.Dest.Y >= rect.Y && actor.Dest.Y <= rect.Y + rect.Height)
                        ||
                        (actor.Dest.Y + actor.Dest.Height >= rect.Y && actor.Dest.Y + actor.Dest.Height <= rect.Y + rect.Height)

                    )
                    .Where(actor => actor.GetType() == typeof(MapTile))
                    .Select(actor => actor as MapTile)
                    .Where(m => m.Type != BlockType.emptyBloc)
                    .ToList();

            /*return graphicObjects
                .Where(actor => actor.GetType() == typeof(MapTile))
                .Select(actor => actor as MapTile)
                .Where(m => m.Dest.Intersects(rect))
                .ToList();*/
        }
    }
}
